package com.tkk.monitoring.analyze;


import com.tkk.monitoring.analyze.config.Line;
import com.tkk.monitoring.analyze.config.Regexp;
import com.tkk.monitoring.analyze.db.DB;
import com.tkk.monitoring.analyze.db.History;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * author: Tkk
 * date: 2015/7/8
 */
public class AnalyzeManager {

    private static final Executor executor = Executors.newFixedThreadPool(200);
    private static final Logger logger = Logger.getLogger(AnalyzeManager.class);

    /**
     * 类型白名单
     */
    private static final Regexp REG_TYPES = new Regexp("white.type");

    /**
     * 域名白名单
     */
    private static final Regexp REG_DOMAINS = new Regexp("white.domain");

    /**
     * 分析器
     */
    private static final Line ANALYZES = new Line("analyze.txt");

    /**
     * @param request
     * @throws Exception
     */
    public static void start(DefaultFullHttpRequest request) {
        AnalyzeTarget target = toTarget(request);
        if (target != null) {
            //
            if (checkTarget(target)) {
                for (String analyzeClassName : ANALYZES.getLines()) {
                    try {
                        AnalyzeWorker worker = (AnalyzeWorker) Class.forName(analyzeClassName).getConstructor(AnalyzeTarget.class).newInstance(target);
                        executor.execute(worker);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            //
            else {
                logger.warn(String.format("站点:[%s] 路径:[%s] 已处理过, 放弃", target.getHost(), target.getPath()));
            }
        }
    }

    /**
     * @param request
     * @return
     */
    private static AnalyzeTarget toTarget(DefaultFullHttpRequest request) {
        AnalyzeTarget target = null;
        String uri = request.getUri();
        String host = null;
        int port = 0;

        Iterator<Map.Entry<String, String>> iterator = request.headers().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            if (StringUtils.equalsIgnoreCase(next.getKey(), "host")) {
                String[] pp = next.getValue().split(":");
                host = pp[0];
                port = pp.length > 1 ? Integer.parseInt(pp[1]) : 80;
                break;
            }
        }


        //
        if (REG_TYPES.isNotMatch(uri) && REG_DOMAINS.isNotMatch(host)) {
            target = new AnalyzeTarget();
            target.setProtocol(request.getProtocolVersion().text().indexOf("HTTP") != -1 ? "http" : "https");
            target.setHost(host);
            target.setPort(port);
            int mark = request.getUri().indexOf("?");
            if (mark != -1) {
                target.setPath(uri.substring(0, mark));
            } else {
                target.setPath(uri);
            }
            target.setMethod(request.getMethod().name().toLowerCase());
            target.setHeaders(request.headers());

            toParam(target, request);
        }
        return target;
    }

    /**
     * 主要判断这个是否渗透过
     *
     * @param target
     * @return
     */
    private static boolean checkTarget(AnalyzeTarget target) {
        List<History> historys = DB.getInstance().getHistory(target);
        if (historys.size() > 0) {
            for (History history : historys) {
                if (history.equals(target)) {
                    return false;
                }
            }
            DB.getInstance().addHistory(target);
            return true;
        } else {
            DB.getInstance().addHistory(target);
            return true;
        }
    }

    private static void toParam(AnalyzeTarget target, DefaultFullHttpRequest request) {
        //解析url的次数
        String uri = request.getUri();
        int mark = uri.indexOf("?");
        if (mark != -1) {
            String paramStr = uri.substring(mark + 1);
            target.setGetParam(toParam(paramStr));
        }

        //解析body的次数
        if (StringUtils.equalsIgnoreCase(request.getMethod().name(), "post")) {
            String paramStr = request.content().toString(Charset.forName("UTF-8"));
            if (StringUtils.isNotBlank(paramStr)) {
                target.setPostBody(paramStr);
                target.setPostParam(toParam(paramStr));
            }
        }
    }


    /**
     * @param body
     * @return
     */
    private static HashMap<String, Object> toParam(String body) {
        HashMap<String, Object> param = new HashMap<String, Object>();
        String[] params = body.split("&");
        for (String p : params) {
            String[] cc = p.split("=");
            if (cc.length > 1) {
                param.put(cc[0], cc[1]);
            } else {
                param.put(cc[0], "");
            }
        }
        return param;
    }
}
